//st7793液晶，16位数据线
//配置接好管脚之后需修改，lcd_dirver.c中WRITE_DATA，CS_0，CS_1，RS_0，RS_1，WR_0，WR_1的定义
#include <Arduino.h>
#include "lcd_driver.h"
#include "lvgl.h"




#define cs 4
#define rs 2
#define rd 15
#define wr 16


#define d0 13
#define d1 12
#define d2 14
#define d3 27
#define d4 26
#define d5 25
#define d6 33
#define d7 32
#define d8 3
#define d9 23
#define d10 22
#define d11 21
#define d12 19
#define d13 18
#define d14 5
#define d15 17

//核心任务
//定期调用 lv_tick_inc(tick_period) 函数并提供以毫秒为单位的调用周期。例如，lv_tick_inc(1) 每毫秒调用一次
static void lv_tick_inc_task( void *pvParameters );
//时间并不重要，但它应该是大约 5 毫秒以保持系统响应
static void lv_timer_handler_task( void *pvParameters );


//绘制缓冲区
/*A static or global variable to store the buffers*/
static lv_disp_draw_buf_t disp_buf;

#define MY_DISP_HOR_RES TFT_XMAX+1      //一行像素

/*Static or global buffer(s). The second buffer is optional*/
static lv_color_t buf_1[MY_DISP_HOR_RES * (TFT_YMAX+1)/10];   //屏幕1/10
static lv_color_t buf_2[MY_DISP_HOR_RES * (TFT_YMAX+1)/10];




//Display driver（显示驱动程序）
static lv_disp_drv_t disp_drv;          /*A variable to hold the drivers. Must be static or global.*/
static void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);//显示回调



/**
 * A simple row and a column layout with flexbox
 */
void lv_example_menu_1(void)
{
    /*Create a menu object*/
    lv_obj_t * menu = lv_menu_create(lv_scr_act());
    lv_obj_set_size(menu, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
    lv_obj_center(menu);

    lv_obj_t * cont;
    lv_obj_t * label;

    /*Create a sub page*/
    lv_obj_t * sub_page = lv_menu_page_create(menu, NULL);

    cont = lv_menu_cont_create(sub_page);
    label = lv_label_create(cont);
    lv_label_set_text(label, "Hello, I am hiding here");

    /*Create a main page*/
    lv_obj_t * main_page = lv_menu_page_create(menu, NULL);

    cont = lv_menu_cont_create(main_page);
    label = lv_label_create(cont);
    lv_label_set_text(label, "Item 1");

    cont = lv_menu_cont_create(main_page);
    label = lv_label_create(cont);
    lv_label_set_text(label, "Item 2");

    cont = lv_menu_cont_create(main_page);
    label = lv_label_create(cont);
    lv_label_set_text(label, "Item 3 (Click me!)");
    lv_menu_set_load_page_event(menu, cont, sub_page);

    lv_menu_set_page(menu, main_page);
}

void setup() {

  // 显示屏初始化
  TFT_Init(cs,rs, rd, wr, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15);	
	TFT_ClearScreen(BLUE);	
  lv_init();

  //初始化lvgl 绘制缓存区
  lv_disp_draw_buf_init(&disp_buf, buf_1, buf_2, MY_DISP_HOR_RES * (TFT_YMAX+1) / 10);
  //Display driver（显示驱动程序）
  lv_disp_drv_init(&disp_drv);            /*Basic initialization*/
  disp_drv.draw_buf = &disp_buf;          /*Set an initialized buffer*/
  disp_drv.flush_cb = my_flush_cb;        /*Set a flush callback to draw to the display*/
  disp_drv.hor_res = TFT_XMAX+1;                 /*Set the horizontal resolution in pixels*/
  disp_drv.ver_res = TFT_YMAX+1;                 /*Set the vertical resolution in pixels*/

  lv_disp_t * disp;
  disp = lv_disp_drv_register(&disp_drv); /*Register the driver and save the created display objects*/



  // lvgl核心任务
  xTaskCreatePinnedToCore(
    lv_tick_inc_task
    ,  "lv_tick_inc_task"   // A name just for humans
    ,  10240  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  2  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,  NULL 
    ,  ARDUINO_RUNNING_CORE);
      // Now set up two tasks to run independently.
  xTaskCreatePinnedToCore(
    lv_timer_handler_task
    ,  "lv_timer_handler_task"   // A name just for humans
    ,  10240  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  1  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,  NULL 
    ,  ARDUINO_RUNNING_CORE);
  Serial.begin(115200,SERIAL_8N1,35,1);
  lv_example_menu_1();
}

void loop() {
    // static char InfoBuffer[512] = {0};
    // vTaskList((char *) &InfoBuffer);
    // Serial.printf("任务名      任务状态 优先级   剩余栈 任务序号\r\n");
    // Serial.printf("\r\n%s\r\n", InfoBuffer);
    // vTaskGetRunTimeStats((char *) &InfoBuffer);
    // Serial.printf("\r\n任务名       运行计数         使用率\r\n");
    // Serial.printf("\r\n%s\r\n", InfoBuffer);
    // vTaskDelay(2000 / portTICK_PERIOD_MS);
    vTaskDelay(2000 / portTICK_PERIOD_MS);
    Serial.printf("loop\r\n");
}


static void lv_tick_inc_task( void *pvParameters )
{
  while (1)
  {
    /* code */
    vTaskDelay(5/portTICK_PERIOD_MS);
    lv_tick_inc(5);
  }
  
}
static void lv_timer_handler_task( void *pvParameters )
{
  while (1)
  {
    /* code */
    lv_timer_handler();
    vTaskDelay(5/portTICK_PERIOD_MS);
  }
}
static void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one
     *`put_px` is just an example, it needs to implemented by you.*/
    TFT_SetWindow(area->x1,area->y1,area->x2,area->y2);
    uint16_t i, j ;
  	for(i=area->x1; i<area->x2+1; i++)
    {
      for (j=area->y1; j<area->y2+1; j++)
      {
        TFT_WriteData((color_p++)->full);
      }
    }
    /* IMPORTANT!!!
     * Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}
